/*************************************
 * 接收客户机上传的文件
 * 首先接收文件名、文件的MD5码、文件大小
 * 然后把文件信息保存到file表中
 * 接收文件
 *
 * 成功返回1，失败返回-1
 *************************************/

#include "../include/server.h"

#define MAX 1000

int serverGets(int sockFd, int curDirID, int ownerID){
    int dataLen = 0;
    int fileSize = 0;
    char fileName[64] = {0};
    char md5str[128] = {0};
    int ret = 0;

    //1、接收客户机传来的文件信息：文件名、文件MD5码、文件大小
    //   (1)接收文件名
    recv(sockFd, &dataLen, 4, 0);
    recv(sockFd, fileName, dataLen, 0);

    //   (2)接收文件MD5码，查看服务器此时是否已经存在该文件，
    recv(sockFd, &dataLen, 4, 0);
    recv(sockFd, md5str, dataLen, 0);
    ret = query_newfile(fileName, curDirID, ownerID);
    if(ret){
        //如果同目录下有同名文件了，拒绝上传，通知客户端
        printf("file already exists!\n");
        send(sockFd, "e", 1, 0);
        return 1;
    }
    
    
    ret = query_count(md5str);
    printf("count = %d\n", ret);
    if(ret > 0){
        //如果已经存在，直接通知客户端上传完成，并把新纪录插入file表中
        send(sockFd, "a", 1, 0);
        //接收文件的大小
        recv(sockFd, &dataLen, 4, 0);
        recv(sockFd, &fileSize, dataLen, 0);
        printf("getsFile succeed!\n");
        insertNewfile(curDirID, fileName, ownerID, md5str, fileSize, 'f');
        return 1;  //执行成功返回1
    }

    //如果不存在，通知客户端发送文件过来
    send(sockFd, "c", 1, 0);

    //接收文件的大小
    recv(sockFd, &dataLen, 4, 0);
    recv(sockFd, &fileSize, dataLen, 0);
    //再创建文件然后接收
    int fd = open(md5str, O_RDWR|O_CREAT, 0666);
    ERROR_CHECK(fd, -1, "open");

    /* printf("filename = %s\n", fileName); */
    /* printf("md5str = %s\n", md5str); */
    /* printf("filesize = %d\n", fileSize); */

    //2、接收文件内容
    //使用splice接收
    int fdPipe[2];  //splice需要借助管道
    pipe(fdPipe);
    int recvSize = 0;
    int recvRet = 0;

    while(recvSize < fileSize){
        //循环接收
        recvRet = splice(sockFd, 0, fdPipe[1], 0, MAX, 0);
        recvRet = splice(fdPipe[0], 0, fd, 0, MAX, 0);
        ERROR_CHECK(recvRet, -1, "splice");
        if(0 == recvRet){
            //客户端发送中断
            printf("client exit!\n");
            break;
        }
        recvSize += recvRet;
    }
    close(fd);
    close(fdPipe[0]);
    close(fdPipe[1]);
    //完成接收，检验接收的文件是否正确
    char newMd5[MD5_STR_LEN+1] = {0};
    Compute_file_md5(md5str, newMd5);
    if(strcmp(md5str, newMd5) == 0){
        //接收成功
        send(sockFd, "a", 1, 0);
        printf("getsFile succeed!\n");
    }
    else{
        //保存的文件和要接收的不一致，接收失败
        send(sockFd, "u", 1, 0);
        printf("getsFile field!\n");
        return -1;
    }
    
    //3、把文件相关信息存入到数据库file表中
    insertNewfile(curDirID, fileName, ownerID, md5str, fileSize, 'f');

    return 1;
}
